package com.cn.service.impl;

import com.alibaba.fastjson.JSON;
import com.cn.entity.PageRequest;
import com.cn.entity.PageVo;
import com.cn.entity.TbStudent;
import com.cn.service.StudentService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private RestHighLevelClient client;
    @Override
    public PageRequest pageRequest(PageVo pageVo) {
        //1.发起请求
        SearchRequest request = new SearchRequest("tiantian02");
        //2.判断是否为空
        buildCondition(pageVo,request);


        request.source().from((pageVo.getPage()-1) * pageVo.getSize()).size(pageVo.getSize());
        try {
            PageRequest pageRequest = handlePage(client,request);
            return pageRequest;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 构建条件
     * @param pageVo
     * @param request
     */
    private void buildCondition(PageVo pageVo, SearchRequest request) {
        String key = pageVo.getKey();
        String stuId = pageVo.getStuId();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (key!=null && !"".equals(key)){
            boolQuery.must(QueryBuilders.matchQuery("name",key));
        }else {
            boolQuery.must(QueryBuilders.matchAllQuery());
        }

        if (stuId!=null && !"".equals(stuId)){
            boolQuery.mustNot(QueryBuilders.rangeQuery("stuId").gte(stuId));
        }

        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(
                //函数
                boolQuery,
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                QueryBuilders.termQuery("isAD", true),
                                //算分函数
                                ScoreFunctionBuilders.weightFactorFunction(10)
                        )
                }
        );
        request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
        request.source().query(functionScoreQueryBuilder);
    }

    private PageRequest handlePage(RestHighLevelClient client, SearchRequest request) throws IOException {
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        List<TbStudent> tbStudents = new ArrayList<>();
        for (SearchHit hit : response.getHits().getHits()) {
            TbStudent tbStudent = JSON.parseObject(hit.getSourceAsString(), TbStudent.class);
            //处理高亮
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!CollectionUtils.isEmpty(highlightFields)){
                //获取结果
                HighlightField name = highlightFields.get("name");
                if (name!=null){
                    //去除高亮的字段
                    String string = name.getFragments()[0].string();
                    tbStudent.setName(string);
                }
            }

            tbStudents.add(tbStudent);
        }
        PageRequest pageRequest = new PageRequest();
        pageRequest.setTotal(response.getHits().getTotalHits().value);
        pageRequest.setData(tbStudents);
        return pageRequest;
    }
}
